package com.hsource.doctorcenter.manager.factory;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Joiner;
import com.hsource.common.utils.CommonResp;
import com.hsource.doctorcenter.conf.dataSource.aspect.SnowflakeIdWorker;
import com.hsource.doctorcenter.domain.clinic.Clinic;
import com.hsource.doctorcenter.domain.doctor.Doctor;
import com.hsource.doctorcenter.domain.doctor.DoctorApi;
import com.hsource.doctorcenter.domain.doctor.DoctorPrice;
import com.hsource.doctorcenter.domain.order.Order;
import com.hsource.doctorcenter.domain.order.OrderDoctor;
import com.hsource.doctorcenter.domain.order.OrderReply;
import com.hsource.doctorcenter.domain.user.UserBase;
import com.hsource.doctorcenter.feign.UserFeignClient;
import com.hsource.doctorcenter.service.clinic.IClinicService;
import com.hsource.doctorcenter.service.doctor.IDoctorPriceService;
import com.hsource.doctorcenter.service.doctor.IDoctorService;
import com.hsource.doctorcenter.service.order.IOrderDoctorService;
import com.hsource.doctorcenter.service.order.IOrderReplyService;
import com.hsource.doctorcenter.service.order.IOrderService;
import com.hsource.doctorcenter.service.problem.ProblemService;
import com.hsource.doctorcenter.util.*;
import com.hsource.doctorcenter.util.enums.CloseCallBackEnum;
import com.hsource.doctorcenter.util.enums.OrderServiceEnum;
import com.hsource.doctorcenter.webSocket.WebSocketServer;
import com.hsource.doctorcenter.webSocket.WebSocketUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @author yangYang
 * @version 1.0
 * @date 2020/9/22 15:17
 * @describe 异步工厂（产生任务用）
 */
@Slf4j
public class AsyncFactory {
    public static void sendMessage(Map<String, Object> requestBodyAnalysis){
        String userId = requestBodyAnalysis.get("user_id").toString();
        if(StringUtils.isNotBlank(userId)) {
            WebSocketServer webSocketServer = SpringUtils.getBean(WebSocketServer.class);
            UserFeignClient userFeignClient = SpringUtils.getBean(UserFeignClient.class);
            String ubImage="";
            try{
                Object userInfo = userFeignClient.getUserInfo(userId);
                CommonResp commonResps = JSONObject.parseObject(JSONObject.toJSONString(userInfo), CommonResp.class);
                JSONObject jo= (JSONObject)commonResps.getData();
                UserBase ub = JSONObject.parseObject(jo.getString("userInfo"), UserBase.class);
                ubImage=ub.getImage();
            }catch (Exception e){
                e.printStackTrace();
            }

            Map<String, String> doctorMap = (Map<String, String>) requestBodyAnalysis.get("doctor");
            String finalUbImage = ubImage;
            JSONObject.parseArray(requestBodyAnalysis.get("content").toString()).stream().forEach(cc->{
                Map<String,String> contentMap = JSONObject.parseObject(cc.toString(), Map.class);
                //消息类型
                String contentType = contentMap.get("type");

                Map<String,String> lmap=new HashMap<>();
                lmap.put("doctorId",doctorMap.get("id"));
                lmap.put("problemId",requestBodyAnalysis.get("problem_id").toString());
                lmap.put("userId",userId);
                lmap.put("duration","0");
                lmap.put("contentType","d");
                lmap.put("doctorImage",doctorMap.get("image"));
                lmap.put("userImage", finalUbImage);
                lmap.put("imageWidth", "0");
                lmap.put("imageHeight", "0");
                lmap.put("type",contentType);
                if(contentType.equals("text")){
                    lmap.put("content",contentMap.get("text"));
                }else{
                    lmap.put("content",contentMap.get("file"));
                    if(contentType.equals("audio")){
                        try {
                            lmap.put("duration",String.valueOf(WebSocketUtil.getDuration(contentMap.get("file"))+2));
                        } catch (MalformedURLException e) {

                        }
                    }
                    if(contentType.equals("image")){
                        try {
                            BufferedImage file = WebSocketUtil.getBufferedImage(contentMap.get("file"));
                            lmap.put("imageWidth", String.valueOf(file.getWidth()));
                            lmap.put("imageHeight", String.valueOf(file.getHeight()));
                        }catch (Exception e){

                        }
                    }
                }
                webSocketServer.sendMessage(userId,JSONObject.toJSONString(lmap));
                try {
                    ProblemService problemService = SpringUtils.getBean(ProblemService.class);
                    problemService.getProblemDetail(userId,requestBodyAnalysis.get("problem_id").toString());
                } catch (ParseException e) {
                    log.error("聊天历史刷新失败"+e.getMessage());
                } catch (NoSuchAlgorithmException e) {
                    log.error("聊天历史刷新失败："+e.getMessage());
                }
            });



        }
    }

    public static TimerTask refreshProblemDetailTimerTask(String userId,String problemId){
        return new TimerTask() {
            @SneakyThrows
            @Override
            public void run() {
                ProblemService problemService = SpringUtils.getBean(ProblemService.class);
                problemService.getProblemDetail(userId,problemId);
            }
        };
    }



    /**
     * 回调处理数据任务
     * @param requestBodyString 回调数据
     * @return
     */
    public static TimerTask callBackReplyDataTimerTask(String requestBodyString){
        return new TimerTask() {
            @SneakyThrows
            @Override
            public void run() {

                SnowflakeIdWorker idWorker = new SnowflakeIdWorker(1, 2);
                String s = String.valueOf(idWorker.nextId());
                Map<String, Object> requestBodyAnalysis = ServletUtils.getRequestBodyAnalysis(requestBodyString);
                //验证sign
                if(SignParams.callBackSign(requestBodyAnalysis)){
                    IOrderReplyService replyService = SpringUtils.getBean(IOrderReplyService.class);
                    IOrderService orderService = SpringUtils.getBean(IOrderService.class);
                    IOrderDoctorService orderDoctorService = SpringUtils.getBean(IOrderDoctorService.class);
                    OrderReply orderReply = new OrderReply();
                    orderReply.setIsPush(0);
                    orderReply.setId(s);
                    orderReply.setUserId(requestBodyAnalysis.get("user_id").toString());
                    orderReply.setContent(JSONObject.toJSONString(requestBodyAnalysis.get("content")));
                    orderReply.setDoctorId(((Map<String,String>)requestBodyAnalysis.get("doctor")).get("id"));
                    orderReply.setStatus(requestBodyAnalysis.get("status").toString());
                    if(requestBodyAnalysis.get("status").toString().contains("reply")){

                        orderReply.setProblemId(requestBodyAnalysis.get("problem_id").toString());
                        orderReply.setLeftInteractions(Integer.parseInt(requestBodyAnalysis.get("left_interactions").toString()));
                        if(!requestBodyAnalysis.containsKey("is_summary")){
                            orderReply.setIsSummary(0);
                        }else {
                            if ((Boolean) requestBodyAnalysis.get("is_summary")) {
                                orderReply.setIsSummary(1);
                            } else {
                                orderReply.setIsSummary(0);
                            }
                        }
                        orderReply.setDoctorId(((Map<String,String>)requestBodyAnalysis.get("doctor")).get("id"));
                        /****************************推送医生消息给用户**********************************/
                        sendMessage(requestBodyAnalysis);
                        /****************************推送医生消息给用户**********************************/


                        int problem_id = Integer.parseInt(requestBodyAnalysis.get("problem_id").toString());


                        /****************************处理图文急诊医生回显信息问题**********************************/
                            Order order = orderService.selectOrderByProblemId(problem_id);
                            if(StringUtils.isNotNull(order)) {
                                Map<String, String> doctorMap = (Map<String, String>) requestBodyAnalysis.get("doctor");
                                OrderDoctor orderDoctor = orderDoctorService.selectOrderDoctorByProblemId(problem_id);
                                if(StringUtils.isNull(orderDoctor)){
                                    OrderDoctor od=new OrderDoctor();
                                    od.setId(UUID.randomUUID().toString().replaceAll("-",""));
                                    od.setDoctorId(doctorMap.get("id"));
                                    od.setPrice(order.getPrice());
                                    od.setConsultType("IT");
                                    od.setOrderId(order.getId());
                                    od.setDoctorName(doctorMap.get("name"));
                                    od.setProblemId(order.getProblemId());
                                    od.setCallTime(Calendar.getInstance().getTime());
                                    od.setProblemStatus(requestBodyAnalysis.get("status").toString());
                                    orderDoctorService.insertOrderDoctor(od);
                                }
                            }
                        /****************************处理图文急诊医生回显信息问题**********************************/
                    }
                    if(requestBodyAnalysis.get("status").toString().contains("_summary")){
                        orderReply.setIsSummary(1);
                        orderReply.setProblemId(requestBodyAnalysis.get("service_id").toString());
                    }
                    replyService.insertOrderReply(orderReply);
                }
            }
        };
    }

    /**
     * 回调处理数据任务
     * @param callBackDataMap
     * @return
     */
    public static TimerTask callBackDataTimerTask(Map<String,Object> callBackDataMap){
        return new TimerTask() {
            @SneakyThrows
            @Override
            public void run() {
               String status = callBackDataMap.get("status").toString();
               //验证sign
               if(SignParams.callBackSign(callBackDataMap)){
                   callBackServiceReverberate(status, callBackDataMap);
               }
            }
        };
    }

    /**
     * 开通快速提问服务
     * @param order 订单信息
     * @return
     */
    public static TimerTask callBackOrdersTimerTask(Order order){
        return new TimerTask() {
            @SneakyThrows
            @Override
            public void run() {
                openingServiceReverberate(order);
            }
        };
    }

    /**
     * 回调服务处理
     * @param status
     * @param callBackDataMap
     */
    public static void callBackServiceReverberate(String status,Map<String,Object> callBackDataMap){
        try {
            Class<?> clazz = Class.forName("com.hsource.doctorcenter.manager.factory.callBackService." + CloseCallBackEnum.getServiceImpl(status));
            Method openingService = clazz.getMethod("callBackDataService", Map.class);
            openingService.invoke(clazz.newInstance(), callBackDataMap);
        }catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
            log.error("处理close回调服务失败："+JSONObject.toJSONString(callBackDataMap));
        }
    }
    /**
     * 调取服务模块并开通
     * @param order 订单参数
     */
    public static void openingServiceReverberate(Order order){
        try {
            Class<?> clazz = Class.forName("com.hsource.doctorcenter.service.order.impl." + OrderServiceEnum.getServiceImpl(order.getOrderType()));
            Method openingService = clazz.getMethod("openingService", Order.class);
            openingService.invoke(clazz.newInstance(), order);
        }catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
            log.error("为查询到改服务的实现方式，即当前服务为："+order.getOrderType());
        }
    }
    /**
     * 同步医生信息
     * @param jsonArray 医生数据
     * @param userId 用户ID
     * @return
     */
    public static TimerTask syncDoctorsByReids(final JSONArray jsonArray,final String userId) {
        return new TimerTask() {
            @Override
            public void run() {
                List<Clinic> clinics = SpringUtils.getBean(IClinicService.class).selectClinicList(new Clinic());
                RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class);
                IDoctorService doctorService = SpringUtils.getBean(IDoctorService.class);
                jsonArray.stream().forEach(jo->{
                    JSONObject jsonObject = JSONObject.parseObject(jo.toString());
                    String doctor_id = jsonObject.get("id").toString();
                    //redis 缓存
                    String key = redisUtil.keyBuilder("doctor", "list");
                    String doctorsDetailed = null;
                    try {
                        Doctor doctor = doctorService.getDoctorsDetailed(userId, doctor_id);

                        consolidatedataDoctor(doctor,jsonObject,clinics,doctor_id);
                        List<DoctorPrice> doctorPrices = consolidatedataDoctorPrice(jsonObject, doctor_id);

                        List<DoctorPrice> th = doctorPrices.stream().filter(a -> a.getConsultType().equals("TH")).collect(Collectors.toList());
                        if(th.stream().count() > 0) {
                            doctor.setTel_price(JSONObject.toJSONString(th.stream().collect(Collectors.toMap(DoctorPrice::getTimeLength, DoctorPrice::getPrice))));
                        }
                        doctor.setPrice(getDoctorMinPrice(doctorPrices));
                        redisUtil.hset(key, doctor_id, doctor);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    } catch (NoSuchAlgorithmException e) {
                        e.printStackTrace();
                    }
                });

            }
        };
    }
    /**
     * 同步医生信息
     * @param jsonArray 医生数据
     * @param userId 用户ID
     * @return
     */
    public static TimerTask syncDoctors(final JSONArray jsonArray,final String userId) {
        return new TimerTask() {
            @Override
            public void run() {
                List<Clinic> clinics = SpringUtils.getBean(IClinicService.class).selectClinicList(new Clinic());
                IDoctorService doctorService = SpringUtils.getBean(IDoctorService.class);
                jsonArray.stream().forEach(jo->{
                    JSONObject jsonObject = JSONObject.parseObject(jo.toString());
                    String doctor_id = jsonObject.get("id").toString();
                    List<DoctorApi> doctors = doctorService.selectDoctorListByDoctorIds(doctor_id);
                    String doctorsDetailed = null;
                    if (doctors.stream().count() <= 0) {
                        try {
                            Doctor doctor =  doctorService.getDoctorsDetailed(userId, doctor_id);
                            consolidatedataDoctor(doctor,jsonObject,clinics,doctor_id);
                            List<DoctorPrice> doctorPrices = consolidatedataDoctorPrice(jsonObject, doctor_id);
                            synDoctorPrice(doctorPrices);
                            doctor.setPrice(getDoctorMinPrice(doctorPrices));
                            doctorService.insertDoctor(doctor);
                        } catch (ParseException e) {
                            e.printStackTrace();
                        } catch (NoSuchAlgorithmException e) {
                            e.printStackTrace();
                        }
                    }
                });

            }
        };
    }

    /**
     * 定向电话同步价格
     * @param doctorJsonObject 医生价格json信息
     * @param doctor_id 医生Id
     */
    public static TimerTask consolidatedataDoctorPriceByPhone(JSONObject doctorJsonObject,String doctor_id){
        IDoctorPriceService doctorPriceService = SpringUtils.getBean(IDoctorPriceService.class);
        return new TimerTask() {
            @Override
            public void run() {
                String telPrice = doctorJsonObject.get("price_info").toString();
                Map<String, BigDecimal> map = JSONObject.parseObject(telPrice, Map.class);
                map.forEach((k, v) -> {
                    DoctorPrice thPrice = new DoctorPrice();
                    thPrice.setDoctorId(doctor_id);
                    thPrice.setOriginalPrice(v.longValue()*100);
                    thPrice.setConsultType("TH");
                    thPrice.setTimeLength(Long.parseLong(k));
                    List<DoctorPrice> doctorPrices = doctorPriceService.selectDoctorPriceList(thPrice);
                    thPrice.setIsFloat(1);
                    thPrice.setPrice(PriceProcessingUtil.priceFloatYuan(v.longValue()));
                    thPrice.setFloatingRatio(PriceProcessingUtil.getPriceRatio());
                    thPrice.setCreateTime(Calendar.getInstance().getTime());
                    if(doctorPrices.stream().count()>0) {
                        thPrice.setId(doctorPrices.get(0).getId());
                        doctorPriceService.updateDoctorPrice(thPrice);
                    }else{
                        doctorPriceService.insertDoctorPrice(thPrice);
                    }
                });
            }
        };
    }

    /**
     * 整合医生价格类型
     * @param doctorJsonObject
     * @param doctor_id
     */
    public static List<DoctorPrice> consolidatedataDoctorPrice(JSONObject doctorJsonObject,String doctor_id){
        String telPrice = doctorJsonObject.get("tel_price").toString();
        Map<String,Integer> map = JSONObject.parseObject(telPrice, Map.class);
        String price = doctorJsonObject.get("price").toString();
        List<DoctorPrice> doctorPrices=new ArrayList<>();
        DoctorPrice itPrice=new DoctorPrice();
        itPrice.setDoctorId(doctor_id);
        itPrice.setConsultType("IT");
        itPrice.setIsFloat(1);
        itPrice.setOriginalPrice(Long.parseLong(price));
        itPrice.setPrice(PriceProcessingUtil.priceFloat(Long.parseLong(price)));
        itPrice.setFloatingRatio(PriceProcessingUtil.getPriceRatio());
        itPrice.setTimeLength(0L);
        itPrice.setCreateTime(Calendar.getInstance().getTime());
        doctorPrices.add(itPrice);
        map.forEach((k,v)->{
            DoctorPrice thPrice=new DoctorPrice();
            thPrice.setDoctorId(doctor_id);
            thPrice.setConsultType("TH");
            thPrice.setIsFloat(1);
            thPrice.setOriginalPrice(v.longValue());
            thPrice.setPrice(PriceProcessingUtil.priceFloat(v.longValue()));
            thPrice.setFloatingRatio(PriceProcessingUtil.getPriceRatio());
            thPrice.setTimeLength(Long.parseLong(k));
            thPrice.setCreateTime(Calendar.getInstance().getTime());
            doctorPrices.add(thPrice);
        });
        return doctorPrices;
    }

    /**
     * 获取医生最小价格
     * @param doctorPrices
     * @return
     */
    public static long getDoctorMinPrice(List<DoctorPrice> doctorPrices){
        doctorPrices=doctorPrices.stream().filter(a->a.getConsultType().equals("IT")).collect(Collectors.toList());
        return doctorPrices.stream().mapToLong(DoctorPrice::getPrice).min().getAsLong();
    }

    /**
     * 同步医生价格数据
     * @param doctorPrices 医生价格集合
     */
    public static void synDoctorPrice(List<DoctorPrice> doctorPrices){
        IDoctorPriceService doctorPriceService = SpringUtils.getBean(IDoctorPriceService.class);
        if(doctorPrices.stream().count() > 0) {
            doctorPriceService.deleteDoctorPriceByDoctorId(doctorPrices.get(0).getDoctorId());
            doctorPrices.stream().forEach(dp -> {
                doctorPriceService.insertDoctorPrice(dp);
            });
        }
    }
    /**
     * 医生数据整合
     * @param doctor
     * @param doctorJsonObject
     * @param clinics
     * @param doctor_id
     * @return
     */
    public static Doctor consolidatedataDoctor( Doctor doctor,JSONObject doctorJsonObject,List<Clinic> clinics,String doctor_id){
        doctor.setPurchase_num(Integer.parseInt(doctorJsonObject.get("purchase_num").toString()));
        doctor.setDoctor_id(doctor_id);
        if(StringUtils.isNotNull(doctor.getTags())) {
            doctor.setTag(Joiner.on(",").join(doctor.getTags()));
        }
        doctor.setIs_famous(doctor.isIs_famous_doctor() ? 0 : 1);
        doctor.setClinic_no(clinics.stream().filter(a -> a.getClinicName().equals(doctor.getClinic_name())).findFirst().get().getClinicNo());
        doctor.setPrice(PriceProcessingUtil.priceFloat(doctor.getPrice()));
        return doctor;
    }

}
